﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using RPGOnline.Controls.Map.Layers.Obstruction.Editors;
using RPGOnline.Properties;

namespace RPGOnline.Controls.Map
{
    public partial class TilesetControl : UserControl
    {
        private MapTileset m_tileset;
        private MapCell[,] m_selectedTiles;
        private int m_selectedTilesWidth;
        private int m_selectedTilesHeight;
        private Point m_selectionStart;

        public TilesetControl()
        {
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.DoubleBuffer, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);

            InitializeComponent();
        }

        public MapTileset Tileset
        {
            get { return m_tileset; }
            set
            {
                m_tileset = value;

                if (m_tileset == null)
                    return;

                Width = m_tileset.PixelWidth;
                Height = m_tileset.PixelHeight;

                m_selectedTiles = null;
                m_selectedTilesWidth = 0;
                m_selectedTilesHeight = 0;
                Invalidate();
            }
        }

        public MapCell[,] SelectedTiles { get { return m_selectedTiles; } }
        public int SelectedTilesWidth { get { return m_selectedTilesWidth; } }
        public int SelectedTilesHeight { get { return m_selectedTilesHeight; } }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            if (m_tileset == null)
                return;

            TextureBrush textureBrush = new TextureBrush(Resources.Background);
            e.Graphics.FillRectangle(textureBrush, ClientRectangle);
            m_tileset.Draw(e.Graphics);
            DrawGrid(e);
            DrawSelectedTiles(e);
        }

        private void DrawSelectedTiles(PaintEventArgs e)
        {
            if (m_selectedTiles == null)
                return;

            Rectangle selectedRect = new Rectangle(m_selectionStart.X * m_tileset.TileSize.Width, m_selectionStart.Y * m_tileset.TileSize.Height, m_selectedTilesWidth * m_tileset.TileSize.Width, m_selectedTilesHeight * m_tileset.TileSize.Height);
            e.Graphics.DrawRectangle(Pens.Red, selectedRect);
        }

        private void DrawGrid(PaintEventArgs e)
        {
            for (int x = 1; x < m_tileset.Width; x++)
            {
                e.Graphics.DrawLine(Pens.LightGray, x * m_tileset.TileSize.Width, 0, x * m_tileset.TileSize.Width, m_tileset.PixelHeight);
            }

            for (int y = 1; y < m_tileset.Height; y++)
            {
                e.Graphics.DrawLine(Pens.LightGray, 0, y * m_tileset.TileSize.Height, m_tileset.PixelWidth, y * m_tileset.TileSize.Height);
            }
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            if (m_tileset == null || e.Button != MouseButtons.Left)
                return;

            int x = e.X / m_tileset.TileSize.Width;
            int y = e.Y / m_tileset.TileSize.Height;

            if (x < 0 || x >= m_tileset.Width || y < 0 || y >= m_tileset.Height)
                return;

            m_selectionStart = new Point(x, y);

            UpdateSelectedTiles(x,y);
            Invalidate();
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);

            if (m_tileset == null) 
                return;

            int x = e.X/m_tileset.TileSize.Width;
            int y = e.Y/m_tileset.TileSize.Height;

            if (x < 0 || x >= m_tileset.Width || y < 0 || y >= m_tileset.Height)
                return;

            if (e.Button == MouseButtons.Left)
            {
                UpdateSelectedTiles(x, y);
                Invalidate();
            }
            else if(e.Button == MouseButtons.Right)
            {
                ObstructionEditorForm obstructionEditorForm = new ObstructionEditorForm(m_tileset, m_tileset.Tiles[x,y], x, y);
                obstructionEditorForm.ShowDialog(this);
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            if (m_tileset == null || e.Button != MouseButtons.Left)
                return;

            int x = e.X / m_tileset.TileSize.Width;
            int y = e.Y / m_tileset.TileSize.Height;

            if (x < 0 || x >= m_tileset.Width || y < 0 || y >= m_tileset.Height)
                return;

            UpdateSelectedTiles(x,y);
            Invalidate();
        }

        private void UpdateSelectedTiles(int x, int y)
        {
            int startX = m_selectionStart.X, startY = m_selectionStart.Y;
            int endX = x, endY = y;
            if(m_selectionStart.X > x)
            {
                startX = x;
                endX = m_selectionStart.X;
            }

            if(m_selectionStart.Y > y)
            {
                startY = y;
                endY = m_selectionStart.Y;
            }

            m_selectedTilesWidth = (endX - startX) + 1;
            m_selectedTilesHeight = (endY - startY) + 1;
            m_selectedTiles = new MapCell[m_selectedTilesWidth, m_selectedTilesHeight];

            int cx = 0;
            for (x = startX; x <= endX; x++, cx++)
            {
                int cy = 0;
                for (y = startY; y <= endY; y++, cy++)
                {
                    m_selectedTiles[cx, cy] = m_tileset.Tiles[x, y];
                }
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            Invalidate();
        }
    }
}
